/**
 * Copyright (c) 2015-2018 iqiyi
 * All rights reserved.
 *
 * Author     : Wang Haibin
 * E-mail     : wanghaibin@qiyi.com
 * Version    :
 * Date       : Fri 01 Feb 2019 03:58:13 PM CST
 * Destription: 获取所有的mount点 并检测指定文件对应的挂载点
 *
 */

#include <iostream>
#include <mntent.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string>
#include <errno.h>

#include <map>

/**
 * 获取所有挂载点信息
 * @return
 */
void GetDeviceInfo(std::map<dev_t, std::string> & devs)
{
    struct mntent *m;
    FILE *f = NULL;
    f = setmntent("/etc/mtab","r"); //open file for describing the mounted filesystems
    if(!f)
        printf("error:%s\n",strerror(errno));
    while ((m = getmntent(f))) {
        struct stat dev_stat;
        stat(m->mnt_dir, &dev_stat);
        devs[dev_stat.st_dev] = m->mnt_dir;
        printf("dir=%s, id=%lu\r\n", m->mnt_dir, dev_stat.st_dev);
    }
    endmntent(f);   //close file for describing the mounted filesystems
}

/**
 * 获取指定文件对应的挂载路径 和挂载设备id
 */
void CheckFileMountDir(std::map<dev_t, std::string> & devs, const char * file)
{
    int ret = -1;
    std::string fullPath=file;
    while(0!=ret) {
        struct stat file_stat;
        ret = stat(fullPath.c_str(), &file_stat);
        if(0==ret) {
            std::string name("ERR");
            std::map<dev_t, std::string>::iterator it = devs.find(file_stat.st_dev);
            if(devs.end() != it) {
                name = it->second;
            }
            printf("file %s mount on id=%ld, mount dir=%s\r\n",
                    file, file_stat.st_dev, name.c_str());
            break;
        } else {
            printf("get error=%s, err=%d, path=%s\r\n", strerror(errno), errno, fullPath.c_str());
            if(0==fullPath.compare("/")) {
                printf("error to find device.");
                break;
            } else {
                size_t pos = fullPath.rfind('/');
                if(pos==std::string::npos) {
                    printf("path error %s.", file);
                    break;
                } else {
                    fullPath = fullPath.substr(0, pos);
                }
            }
        }
    }
}

int main()
{
    std::map<dev_t, std::string> devs;
    GetDeviceInfo(devs);
    CheckFileMountDir(devs, "/data1/www/whb.txt");
    return 0;
}

